package com.ironman.analyze.core.compute;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.ironman.analyze.core.compute.base.BaseComputer;
import com.ironman.analyze.core.compute.entity.WindEnvWindowData;
import com.ironman.common.entity.WindData;
import com.ironman.common.params.WindParam;
import com.ironman.common.structure.FixedSizeLinkedBlockingDeque;
import com.ironman.common.structure.WindVectorData;
import com.ironman.common.structure.WindWindowData;
import com.ironman.common.util.WindowCalUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 风矢量计算
 */
@Slf4j
public class AllWindVectorComputer implements BaseComputer<WindData, WindEnvWindowData> {

    private final Integer windowSize;

    private final FixedSizeLinkedBlockingDeque<WindVectorData> windVectorDataFixedSizeLinkedBlockingDeque;

    private final Map<Date, List<WindEnvWindowData>> windAllWindowDataMapList;


    public AllWindVectorComputer(WindParam windParam, Map<Date, List<WindEnvWindowData>> windAllWindowDataMapList) {
        this.windowSize = windParam.getWindowSize();
        this.windVectorDataFixedSizeLinkedBlockingDeque = new FixedSizeLinkedBlockingDeque<>(windowSize);
        this.windAllWindowDataMapList = windAllWindowDataMapList;
    }

    @Override
    public void computeWindowData(List<WindData> dataList) {
        for (WindData windData : dataList) {
            this.windVectorDataFixedSizeLinkedBlockingDeque.offerLast(WindowCalUtil.preCompute(windData.getTrainingBoatCode(), windData.getTs(), windData.getDirection(), windData.getSpeed()));
            List<WindVectorData> windVectorDataList = this.windVectorDataFixedSizeLinkedBlockingDeque.subList(windowSize, true);
            if (CollectionUtil.isEmpty(windVectorDataList)) {
                log.debug("未能达到窗口大小，目标窗口大小为{}", windowSize);
                continue;
            }

            // 移除不在窗口数据
            Date maxTs = windVectorDataList.get(windowSize - 1).getArrivalDate();
            windVectorDataList = windVectorDataList.stream().filter(n -> DateUtil.between(n.getArrivalDate(), maxTs, DateUnit.SECOND) < windowSize).collect(Collectors.toList());
            log.debug("风开启窗口计算 目标窗口大小 {} 实际数据大小 {}", windowSize, windVectorDataList.size());

            WindWindowData windWindowData = WindowCalUtil.computeWindowData(windVectorDataList);
            WindEnvWindowData windEnvWindowData = new WindEnvWindowData(windWindowData.getArrivalDate(), windWindowData.getTrainingBoatCode(), windWindowData.getSpeed(), windWindowData.getDirection());
            syncData(windEnvWindowData);
        }
    }

    @Override
    public void syncData(WindEnvWindowData windowData) {
        Date ts = windowData.getTs();
        List<WindEnvWindowData> windEnvWindowDataList = windAllWindowDataMapList.get(ts);
        if (CollectionUtil.isEmpty(windEnvWindowDataList)) {
            windEnvWindowDataList = new ArrayList<>();
            windAllWindowDataMapList.put(ts, windEnvWindowDataList);
        }
        windEnvWindowDataList.add(windowData);
    }


}
